转场的本质是下一场景(子 VC)的视图替换当前场景(子 VC)的视图以及相应的控制器(子 VC)的替换,表现为当前视图消失和下一视图出现,
转场的本质是下一场景(子 VC)的视图替换当前场景(子 VC)的视图以及相应的控制器(子 VC)的替换,表现为当前视图消失和下一视图出现,
在视图结构上,只保留一个子 VC 的视图,所
在视图结构上,只保留一个子 VC 的视图,所以转场的本质是下一场景(子 VC)的视图替换当前场景(子 VC)的视图以及相应的控制器(子 VC)的替换,表现为当前视图消失和下一视图出现,
iOS 7 以协议的方式开放了自定义转场的 API,协议的好处是不再拘泥于具体的某个类,只要是遵守该协议的对象都能参与转场,非常灵活
这里除了<UIViewControllerTransitioningDelegate>是
这里除了<UIViewControllerTransitioningDelegate>是 iOS 7 新增的协议,
转场发生时,UIKit 将要求转场代理将提供转场动画的核心构件:动画控制器和交互控制器(可选的);由我们实现。
在动画控制器里,参与转场的视图只有 fromView 和 toView 之分,与转场方式无关
三大转场代理协议的方法不尽相同,但它们返回的动画控制器遵守的是同一个协议,因此可以将动画控制器封装作为第三方动画控制器在其他控制器的转场过程中使用。
转场的本质是下一个场景的视图替换当前场景的视图,从当前场景过渡下一个场景
目前为止,官方支持以下几种方式的自定义转场:
三种转场代理,对应上面三种类型的转场:
,5个协议只需要我们操心3个;实现一个最低限度可用的转场动画,我们只需要提供上面五个组件里的两个:转场代理和动画控制器即可,还有一个转场环境是必需的,不过这由系统提供;当进一步实现交互转场时,还需要我们提供交互控制器,也有现成的类供我们使用。
这个阶段要做两件事,提供转场代理并由代理提供动画控制器。
根视图并未参与转场
根视图 presentingView 也就是 fromView 参与了转场。
了 Modal 转场和容器 VC 的转场对 fromView 的处理差异:容器 VC 的转场结束后 fromView 会被主动移出视图结构,
UIModalPresentationCustom 这种模式下的 Modal 转场结束时 fromView 并未从视图结构中移除;UIModalPresentationFullScreen 模式的 Modal 转场结束后 fromView 依然主动被从视图结构中移除了
Custom 模式下,presentingView 并不受 containerView 管理,这时通过 viewForKey: 方法来获取 presentingView 得到的是 nil,必须通过 viewControllerForKey: 得到 presentingVC 后来获取。因此在 Modal 转场中,较稳妥的方法是从 fromVC 和 toVC 中获取 fromView 和 toView。
UIViewController 的 modalPresentationStyle 属性为 .Custom 或 .FullScreen 时,我们就有机会定制转场效果,此时 modalTransitionStyle 指定的转场动画将会被忽略。
在 presentation 后,fromView(presentingView) 未被移出视图结构,在 dismissal 中,注意不要像其他转场中那样将 toView(presentingView) 加入 containerView 中,否则本来可见的 presentingView 将会被移除出自身所处的视图结构消失不见
对于 Custom 模式,我们可以参照其他转场里的处理规则来打理:
通过 viewForKey: 获取的视图是 viewControllerForKey: 返回的控制器的根视图,或者 nil。 viewForKey: 方法返回 nil 只有一种情况:
UIModalPresentationCustom 模式下的 Modal 转场 ,通过此方法获取 presentingView 时得到的将是 nil,在后面的 Modal 转场里会详细解释
系统以一种解耦的方式使得动画控制器,交互控制器,转场环境对象互相协作,我们只需要使用 UIPercentDrivenInteractiveTransition 的三个同名方法来控制进度就够了。
交互控制器控制转场的过程就像将动画控制器实现的动画制作成一部视频,我们使用手势或是其他方法来控制转场动画的播放,可以前进,后退,继续或者停止。
不管是什么交互方式,使用什么转场方式,都是在使用这三个方法控制转场的进度。对于交互式转场,交互手段只是表现形式,本质是驱动转场进程。
取消转场的代码执行后, self.navigationController 返回的依然还是是 nil,怎么让控制器回到 NavigationController 的控制器栈顶。对于这种情况,UIKit 自动替我们恢复了,不需要我们操心(可能你都没有意识到这回事
场协调器除了上面的两种关键作用外,也在 iOS 8 中的适应性布局中担任重要角色,可以查看<UIContentContainer>协议中的方法,其中响应尺寸和屏幕旋转事件的方法都包含一个转场协调器对象,视图的这种变化也被系统视为广义上的 transition,参数中的转场协调器也由 UIKit 提供。
UIPercentDrivenInteractiveTransition 类是一个系统提供的交互控制器,在转场代理的相关方法里提供一个该类实例就够了
UIViewController 自身就有方法跟踪 Modal 状态。
通过控制器的转场代理提供 UIPresentationController 的子类对 Modal 转场进行进一步的定制。
选择是否移除 presentingView
presentedViewController.transitionCoordinator()?.animateAlongsideTransition({ _ in
presentedViewController.transitionCoordinator()?.animateAlongsideTransition({ _ in
OverlayPresentationController 类接手了 dimmingView 的工作后,需
返回 true 时,presentation 结束后 presentingView 被移除,在 dimissal 结束后 UIKit 会自动将 presentingView 恢复到原来的视图结构中
,<UIContentContainer>协议用于响应视图尺寸变化和屏幕旋转事件,
self.navigationController?.delegate = SDENavigationControllerDelegate()